// ==UserScript==
// @name           Shack - Working Collapse
// @namespace      http://www.lmnopc.com/
// @description    Makes the collapse buttons actually work!
// @include http://shacknews.com/laryn.x?*
// @include http://*.shacknews.com/laryn.x?*
// ==/UserScript==


	/*
	Amazon Wish List: http://amazon.com/gp/registry/1YRBQ22VGN9PR

	------------------------------------------------------------
	Shack Working Collapse
	Author: Thom Wetzel - www.lmnopc.com
	(C)2007-2008 Thom Wetzel
	------------------------------------------------------------

	Big thanks to arhughes for making his collapse script that got me
	thinking about even doing this, but I trashed it and started over
	because his script was doing a bunch of things you shouldn't really
	do in Greasemonkey scripts.

	REVISIONS:

	2007-06-26
		- Initial Release

	2007-06-26.b
		- Fixed the show_post bug.  There's something weird going on but it works now.

	2007-07-19
		- Fixed the problem with videos showing up when posts are collapsed

	2008-01-23
		- Added setValue hack for dealing with new and improved(?) version of Greasemonkey
		- Doubled number of stored threads from 50 to 100 and created MAX_THREADS variable
			so users can easily adjust it so they can balance their own performance vs. qty

	2008-12-12
		- Got rid of the code that dealt with the +/- things (Bull had issues ... lol)

   2009-05-14
      - Ported to Chrome 

	*/


if ((script_enabled('collapse_post') == "true") && (location.href.indexOf('laryn.x') != -1))
{
    var MAX_THREADS = 100;

    var benchmarkTimer = null;
    var scriptStartTime = getTime();
    function getTime() { benchmarkTimer = new Date(); return benchmarkTimer.getTime(); }

    function isFunction(a) { return typeof a == 'function'; }
    function isObject(a) { return (a && typeof a == 'object') || isFunction(a); }
    function isArray(a) { return isObject(a) && a.constructor == Array; }

    // Hideous Greasemonkey 0.7 hack
    function setValue(key, value) {
        window.setTimeout(
				function() {
				    GM_setValue(key, value);
				}, 0);
    }

    // reads in an array from a Greasemonkey variable
    function loadArray(key) 
	 {
        var arr = new Array();

        arr = GM_getValue(key);
        if (arr) 
		  {
            arr = arr.split(",");
        }

        if (!isArray(arr)) 
		  {
            arr = new Array();
        }

        return arr;
    }

    function findThread(tid) 
	 {
        for (var i = 0; i < arrCollapsedThreads.length; i++) 
		  {
            if (arrCollapsedThreads[i] == tid) 
				{
                return i;
            }
            else if (arrCollapsedThreads[i] < tid) 
				{
                return -1;
            }
        }
        return -1;
    }

    // used in sort() method to reverse sort the list
    function reverseCompare(a, b) 
	 {
        return b - a;
    }

    function addThread(tid) 
	 {
        // don't allow duplicates
        if (findThread(tid) != -1) 
		  {
            return;
        }

        // don't allow more than MAX_THREADS threads in the list
        while (arrCollapsedThreads.length >= MAX_THREADS) 
		  {
            arrCollapsedThreads.pop();
        }

        // add the new thread to the array
        arrCollapsedThreads.push(tid);

        // sort the array
        arrCollapsedThreads.sort(reverseCompare);

        // save the new array
        setValue(sCollapsedThreads_Key, String(arrCollapsedThreads));
    }

    function removeThread(tid) 
	 {
        // find thread in the array
        var idx = findThread(tid);
        if (idx == -1) {
            return;
        }

        // remove the thread from the array
        arrCollapsedThreads.splice(idx, 1);

        // save the updated array
        setValue(sCollapsedThreads_Key, String(arrCollapsedThreads));
    }


    // load list of collapsed threads
    var arrCollapsedThreads = new Array();
    var sCollapsedThreads_Key = 'shackCommentsCollapsePost';
    arrCollapsedThreads = loadArray(sCollapsedThreads_Key);

    // replace functions with our stand-ins
    if (typeof(shackcollapse_close_post) == 'undefined') 
	 {
        shackcollapse_close_post = close_post;
        close_post = function(id) {

            // call original function
            shackcollapse_close_post(id);

            // 2008-12-12 :
            // Make sure this is a root node before adding it to the list
            // of collapsed threads to prevent subthreads from being hidden
            if (document.getElementById('root_' + id) != null) {
                // store this thread id
                addThread(id);
            }
        }
    }

    function removeClassFromElement(el, nukeClass)
	 {
        // split classes into array
        var classArray = String(el.className).split(' ');

        // make sure the class we're removing is in classArray
        if (classArray.indexOf(nukeClass) == -1) {
            alert('removeClassFromElement Error : "' + nukeClass + '" not found in "' + el.className + '"');
            return;
        }

        var newClasses = '';

        for (var i = 0; i < classArray.length; i++) {
            if (classArray[i] != nukeClass) {
                if (newClasses.length) {
                    newClasses += ' ';
                }
                newClasses += classArray[i];
            }
        }
        el.className = newClasses;
    }

    function getElementByClassName(oElm, strTagName, strClassName) {
        var arrElements = oElm.getElementsByTagName(strTagName);
        var oElement;
        for (var i = 0; i < arrElements.length; i++) {
            oElement = arrElements[i];
            if (oElement.className.indexOf(strClassName) == 0) {
                return oElement;
            }
        }
    }

    if (typeof(shackcollapse_show_post) == 'undefined') 
    {
        shackcollapse_show_post = show_post;
        show_post = function(article_id) {
            // call original function
            shackcollapse_show_post(article_id);

            // remove ul.hidden -- which is really weird but I'll go with it if it makes the stupid thing work.  ;)
            var article_node = document.getElementById("item_" + article_id);
            var ul_node = getElementByClassName(article_node, 'ul', 'hidden');
            if (ul_node) {
                removeClassFromElement(ul_node, 'hidden');
            }

            // remove this thread id from our list
            removeThread(article_id);
        }
    }

    if (typeof(shackcollapse_toggle_collapse) == 'undefined') 
    {
        shackcollapse_toggle_collapse = toggle_collapse;
        toggle_collapse = function(id) {        
            // call original function
            shackcollapse_toggle_collapse(id);

            // we have to find the UL under the item_[id] to see if it's hidden or not
            var collapsableUl = document.getElementById('item_' + id).getElementsByTagName('ul')[0];

            if (collapsableUl.className.indexOf('hidden') == -1) {
                removeThread(id);
            }
            else {
                addThread(id);
            }
        }
    }
		
	/* moved to shackscripts.css

    // add CSS to the page to hide collapsed embedded videos
    GM_addStyle('div.collapsed object { visibility: hidden; };');
	*/

	
	

 
	
    // check root posts for collapsed threads
    var items = document.evaluate("//div[contains(@class, 'root')]", document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
    for (item = null, i = 0; item = items.snapshotItem(i); i++) {
        var rootId = item.id.substr(5);
        if (findThread(rootId) > -1) {
            shackcollapse_close_post(rootId);
        }
    }

    // log execution time
    if (GM_log) {
        GM_log('collapse.js: ' + (getTime() - scriptStartTime) + 'ms');
    }
}